package pers.cz.thread;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @program: PostGirl-panent
 * @description: 分表查询线程池
 * @author: Cheng Zhi
 * @create: 2022-05-03 22:03
 **/
public class PartitionQueryThreadExecutor {

    public static int PRODUCER_CORE_POOL_SIZE = 5;    // 核心线程数
    public static int PRODUCER_MAX_POOL_SIZE = 5;    // 最大线程池
    public static int PRODUCER_KEEP_ALIVE_TIME = 1;   // 线程等待时间
    public static int PRODUCER_MAX_BUFF_SIZE = 100;   // 缓存大小


    private boolean isProducerStop = false;            // 线程是否停止

    private ThreadPoolExecutor producerExecutor;

    public static PartitionQueryThreadExecutor threadExecutor;
    private int dataType;

    private PartitionQueryThreadExecutor(Integer dataType) {
        this.dataType = dataType;
    }

    private PartitionQueryThreadExecutor(Integer dataType, int corePoolSize, int maxPoolSize) {
        this.dataType = dataType;
        this.PRODUCER_CORE_POOL_SIZE = corePoolSize;
        this.PRODUCER_MAX_POOL_SIZE = maxPoolSize;
    }

    /**
     * 提交线程
     * @param worker
     */
    public void executeTask(Worker worker) {
        this.producerExecutor.execute(worker);
    }

    /**
     * 单例模式实例化对象
     * @param dataType
     * @return
     */
    public static PartitionQueryThreadExecutor getInstance(Integer dataType) {

        if (threadExecutor == null) {
            threadExecutor = new PartitionQueryThreadExecutor(dataType);
            // 初始化时就开启线程池
            threadExecutor.start();
        }
        return threadExecutor;
    }

    /**
     * 单例模式实例化对象
     * @param dataType
     * @param corePoolSize
     * @param maxPoolSize
     * @return
     */
    public static PartitionQueryThreadExecutor getInstance(Integer dataType, int corePoolSize, int maxPoolSize) {

        if (threadExecutor == null) {
            threadExecutor = new PartitionQueryThreadExecutor(dataType, corePoolSize, maxPoolSize);
            // 初始化时就开启线程池
            threadExecutor.start();
        }
        return threadExecutor;
    }

    /**
     * 初始化线程池
     */
    public void start() {
        this.startProducerExecutor();
    }

    /**
     * 初始化生产者线程池
     */
    private void startProducerExecutor() {

        // 从redis中获取线程参数
        Map<String, String> cacheMap = new HashMap<>();
        Integer corePoolSize = PRODUCER_CORE_POOL_SIZE;

        Integer maxPoolSize = PRODUCER_MAX_POOL_SIZE;

        Integer keepAliveTime = PRODUCER_KEEP_ALIVE_TIME;

        BlockingQueue<Runnable> blockingQueue = new LinkedBlockingDeque<Runnable>();
        this.producerExecutor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, blockingQueue);
        this.producerExecutor.allowCoreThreadTimeOut(true);

    }

    /**
     * 线程池停止
     */
    public void stop() {

        this.stopProducerExecutor();
    }

    /**
     * 停止生产者线程池
     */
    private void stopProducerExecutor(){
        this.producerExecutor.shutdown();
        try{

            while(true){
                if(this.producerExecutor.awaitTermination(1, TimeUnit.SECONDS)){
                    this.producerExecutor.shutdownNow();
                    break;
                }
            }
        }catch(Exception e){
            return;
        }
    }

    /**
     * 判断线程池是否全部终止
     * @return
     */
    public boolean isCompleteStop() {

        while(true) {
            if (this.producerExecutor.isTerminated()) {
                System.out.println("所有的子线程都结束了！");

                break;

            }
        }
        return true;
    }

    public boolean isProductThreadStop(){
        this.isProducerStop = this.producerExecutor.isTerminated();

        return this.isProducerStop;
    }

    /**
     * 判断线程是否全部执行完成
     * @return
     */
    public boolean isAllStop() {

        // 当线程池完成的线程数等于线程池中的总线程数
        return this.producerExecutor.getTaskCount() == this.producerExecutor.getCompletedTaskCount();
    }
}
